package main

import (
	"fmt"
	"github.com/facebookgo/httpcontrol"
	"io"
	_ "io/ioutil"
	"net/http"
	"os"
	_ "path/filepath"
	"strings"
	"time"
)

type Func func(method, url, optional string)

var op = map[string]Func{
	"HEAD":     do_head,
	"GET":      do_get,
	"POST":     do_post,
	"PUT":      do_put,
	"DELETE":   do_delete,
	"TRUNCATE": do_truncate,
	"OPEN":     do_open,
	"APPEND":   do_append,
	"CLOSE":    do_close,
	"COPY":     do_copy,
	"MOVE":     do_move,
	"LINK":     do_link,
	"UNLINK":   do_unlink,
}
var client = &http.Client{
	Transport: &httpcontrol.Transport{
		RequestTimeout: 0 * time.Second,
	},
}
var 看看怎么使用的吧 = `usage:
				bblclient HEAD <url>
				bblclient GET <url> <file>
				bblclient POST <url> <file>
				bblclient PUT <url> <file>
				bblclient DELETE <url>
				bblclient TRUNCATE <url>
				bblclient MOVE <url> <to>
				bblclient COPY <url> <to>
				bblclient LINK <url> <to>
				bblclient UNLINK <url>
			`

func main() {
	if len(os.Args) < 2 {
		fmt.Println(看看怎么使用的吧)
		return
	}
	opcode := strings.ToUpper(os.Args[1])
	if handler, exist := op[opcode]; exist {
		if len(os.Args) > 3 {
			handler(opcode, os.Args[2], os.Args[3])
		} else {
			handler(opcode, os.Args[2], "")
		}
	} else if "H" == opcode || "HELP" == opcode {
		fmt.Println(看看怎么使用的吧)
	} else {
		fmt.Println(fmt.Println("unknown", os.Args[1]))
	}
}

func do_head(method, url, optional string) {
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(resp.Status)
	printh(resp.Header)

}
func printh(h http.Header) {
	for key, value := range h {
		fmt.Printf("%v: %v\r\n", key, value)
	}
}
func do_get(method, url, optional string) {
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	printh(req.Header)
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status)
	printh(req.Header)
	printh(resp.Header)
	fd, err := os.OpenFile(optional, os.O_CREATE|os.O_TRUNC|os.O_RDWR, os.ModePerm)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer fd.Close()
	written, err := io.Copy(fd, resp.Body)
	fmt.Println("read", written, "==>", optional)
	// if dir, err := os.Getwd(); err != nil {
	// 	fmt.Println(err)
	// } else {
	// 	dir1, file := filepath.Split(req.URL.Path)
	// 	os.MkdirAll(filepath.Join(dir, dir1), os.ModePerm)
	// 	fd, err := os.OpenFile(filepath.Join(dir, dir1, file), os.O_CREATE|os.O_TRUNC|os.O_RDWR, os.ModePerm)
	// 	if err != nil {
	// 		fmt.Println(err)
	// 		return
	// 	}
	// 	defer fd.Close()
	// 	// b, err := ioutil.ReadAll(resp.Body)
	// 	// if err != nil {
	// 	// 	fmt.Println(err)
	// 	// 	return
	// 	// }
	// 	// fd.Write(b)
	// 	//written := len(b)
	// 	written, err := io.Copy(fd, resp.Body)
	// 	fmt.Println("read", written, "==>", filepath.Join(dir, dir1, file))
	// }

}
func do_post(method, url, optional string) {
	fd, err := os.OpenFile(optional, os.O_RDONLY, os.ModePerm)
	if err != nil {
		fmt.Println(err)
		return
	}

	req, err := http.NewRequest(method, url, fd)
	if err != nil {
		fmt.Println(err)
		return
	}

	req.Header.Set("Content-Type", "application/octet-stream")
	req.Header.Set("Connection", "close")
	printh(req.Header)
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(resp, err)
		return
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status)
	printh(resp.Header)

}

func do_put(method, url, optional string) {
	do_post(method, url, optional)
}

func do_delete(method, url, optional string) {
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(resp.Status)
	printh(resp.Header)
}
func do_truncate(method, url, optional string) {
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(resp.Status)
	printh(resp.Header)
}
func do_move(method, url, optional string) {
	if len(optional) == 0 || !strings.HasPrefix(optional, "/") {
		fmt.Println("usage: bblcient move http://127.0.0.1:7600/abc/bcd/bbb /abc/bcd/aaa")
	}
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Add("X-RENAME-TO", optional)
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(resp.Status)
	printh(resp.Header)
}
func do_link(method, url, optional string) {
	if len(optional) == 0 || !strings.HasPrefix(optional, "/") {
		fmt.Println("usage: bblcient link http://127.0.0.1:7600/abc/bcd/bbb /abc/bcd/aaa")
	}
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Add("X-LINK-TO", optional)
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(resp.Status)
	printh(resp.Header)
}
func do_unlink(method, url, optional string) {
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(resp.Status)
	printh(resp.Header)
}
func do_open(method, url, optional string) {

}
func do_append(method, url, optional string) {

}
func do_close(method, url, optional string) {

}

func do_copy(method, url, optional string) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	printh(req.Header)
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer resp.Body.Close()
	fmt.Println(resp.Status)
	printh(req.Header)
	printh(resp.Header)

	///////////////////////////

	req1, err := http.NewRequest("PUT", "http://"+req.URL.Host+optional, resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}

	req1.Header.Set("Content-Type", "application/octet-stream")
	req1.Header.Set("Connection", "close")
	printh(req1.Header)
	resp1, err := client.Do(req1)
	if err != nil {
		fmt.Println(resp1, err)
		return
	}
	defer resp1.Body.Close()
	fmt.Println(resp1.Status)
	printh(resp1.Header)
}
